import json
from datetime import date, datetime
from typing import Iterable

import sqlalchemy
from django.core.serializers.json import DjangoJSONEncoder
from sqlalchemy.ext.declarative import DeclarativeMeta

from Utils.Functions import BASE_DATE_FORMAT, NOT_SPILT_DATE_FORMAT
from WebServer.blog.models import CodeTagDate


def in_sql(key_words: Iterable) -> str:
    """ 返回('k1','k2','k3') """
    if not key_words:
        return ""
    base_li = list()
    base_li.extend(key_words)
    return str(base_li).replace("[", '(').replace("]", ')')


def format_str_2_quote(string):
    return format_str_spilt_2_quote(string, "+、\\n\\t\\r", ",")


def strip_str_strict(string: str) -> str:
    if string:
        return string.replace(" ", "")
    return string


# 2019-2-19
# 返回datetime.date
def get_date_from_str(date_s: str) -> date:
    """通过字符串类型的时间获取对应的datetime.date类型的时间
    :argument
        date_s : 'XXXX-XX-X'

    Returns:
        datetime.date(YYYY,MM,DD)
        """
    dss = date_s.split("-")
    if len(dss) > 2:
        return date(int(dss[0]), int(dss[1]), int(dss[2]))
    return date(0, 0, 0)


# 将不同格式的分隔符替换为,
def format_str_spilt_2_quote(string, need_replace_sequence: Iterable = '+、', repl=',') -> str:
    if string:
        for cha in need_replace_sequence:
            string = string.replace(cha, repl)
    # .replace("-",",")\
    return string


def is_black_str(string):
    if not string:
        return True
    return True if string.strip() == '' else False


def parse_date_from_s(date_s, input_format=NOT_SPILT_DATE_FORMAT):
    import datetime
    strptime, strftime = datetime.datetime.strptime, datetime.datetime.strftime
    date_s = str(date_s)
    return strptime(date_s, input_format).date()

def format_date_2_s(date_ , output_format=NOT_SPILT_DATE_FORMAT):
    import datetime
    strptime, strftime = datetime.datetime.strptime, datetime.datetime.strftime
    return date_.strfime(output_format).date()


def reformat_s_date_s(date_s, input_format=BASE_DATE_FORMAT, output_format=NOT_SPILT_DATE_FORMAT):
    import datetime
    strptime, strftime = datetime.datetime.strptime, datetime.datetime.strftime
    date_s = str(date_s)
    return parse_date_from_s(date_s, input_format).strftime(output_format)

def parse_rp_2_dicts(rp):
    d, a = {}, []
    for rowproxy in rp:
        # rowproxy.items() returns an array like [(key0, value0), (key1, value1)]
        for column, value in rowproxy.items():
            # build up the dictionary
            d = {**d, **{column: value}}
        a.append(d)
    return a

def parse_rp_2_rows(rp):
    rows_ = []
    for rowproxy_ in rp:
        # rowproxy.items() returns an array like [(key0, value0), (key1, value1)]
        rows_.append(rowproxy_.values())
    return rows_

def parse_rp_2_one_rows(rp):
    rows_ = []
    for rowproxy_ in rp:
        # rowproxy.items() returns an array like [(key0, value0), (key1, value1)]
        rows_.extend(rowproxy_.values())
    return rows_

class DateEncoder(DjangoJSONEncoder):
    def default(self, obj):
        filter_set = {'_sa_instance_state'}
        # print("parse type :".format(type(obj)))
        if isinstance(obj, date):
            return obj.strftime("%Y-%m-%d")
        # elif isinstance(type(obj), sqlalchemy.ext.declarative.api.DeclarativeMeta) or isinstance(obj, CodeTagDate):
        #     # elif issubclass(type(obj), sqlalchemy.ext.declarative.api.Base):
        #     print("parse type :".format(type(obj)))
        #     base_dict = dict()
        #     # has_model = False
        #     for it_ in obj.__dict__.items():
        #         if it_[0] in filter_set or it_[0].startswith("_"):
        #             continue
        #         base_dict[it_[0]] = self.default(it_[1])
        #         # json.JSONEncoder.default(self, it_[1])
        #     return super().default(base_dict)
        #     # DjangoJSONEncoder.default(self, base_dict)
        else:
            return super().default(obj)

def replace_split(generic_content:str):
    return generic_content.replace("\r","\n")

def filter_and_sort_list(combine_res_, kws:Iterable):
    res_set = set()
    for kw_ in kws:
        res_set.update((set(filter(lambda it_: it_.find(kw_) > -1, combine_res_))))
    return list(res_set)